iT邦幫忙

2023 iThome 鐵人賽

DAY 16
0

資料驗證介紹

資料驗證是進到 controller 後第一件處理的事情,通常會用下列寫法(當然每個人coding style 很不一樣):

//查看傳入的資料格式
dd($request->input())

//資料驗證
$validated = $request->validate([
		'id'   => "required|int",
		'name' => "required|string",
]);

//取用驗證過的資料
Group::create($validated);

上面提供一個很簡單的舉例說明相關用法。

在昨天 儲存團購資料 的功能裡面,我用到了一些資料驗證邏輯:

$validated = $request->validate([
    'group_name'           => 'required|string|min:3|max:50',
    'organizer_id'         => 'required|int',
    'close_price'          => 'nullable|decimal:0,2',
    'close_date'           => 'nullable|date|after_or_equal:today',
    'allow_insert_product' => 'nullable',
    'status'               => 'required|int',
 ]);
  1. 是否必填:required 必填 / nullable 非必填
  2. 資料格式:string 字串 / int 整數 / decimal:0,2 小數點後 0~2 位數的數字 / date 時間格式
  3. 資料範圍:min 至少幾字符 / max 最多幾字符 / after_or_equal:today 日期不可早於今天

官方文件還有很多用法,非常值得一看,在這裡擋掉可省下後面很多程式碼。

官方文件中文版官方文件

下面針對幾個驗證方式,經過其他好想工作室夥伴建議值得認識的規則:

巢狀結構驗證

昨天有講到,後面在新增產品資料時,我的程式邏輯會一次新增好多筆產品資料(如下圖)

https://ithelp.ithome.com.tw/upload/images/20231001/201628931CQUQrBp0H.png

資料的結構是像下圖這樣的三層結構

https://ithelp.ithome.com.tw/upload/images/20231001/20162893zbaO5FzLz6.png

在驗證上, Laravel 用 . 分層,並用 * 代表萬用字符

$validated = $request->validate([
		'group_id'            => 'required|int',
		'data'                => 'required|array',
		'data.*.product_name' => 'nullable|string|max:255',
				// 第三層的 product_name 之驗證規則
		'data.*.price'        => 'nullable|required_with:data.*.product_name|int'
				// 第三層的 price 之驗證規則
]);

圖片檔案驗證

上傳圖片也可進行驗證,

Validator::validate($input, [
		'photo' => [
        'required',
        File::image()
            ->min(1024) // 檔案大小至少需 1MB
            ->max(12 * 1024)  // 檔案大小至多 12MB
            ->dimensions(Rule::dimensions()->maxWidth(1000)->maxHeight(500)),
							// 圖片長寬尺寸像素限制
],

另一種撰寫方式 (coding style 不同而已)

'group_image' => 'nullable|file|mimes:jpeg,png|dimensions:max_width=800,max_height=600',

依據別的欄位驗證

Validator::make($request->all(), [
    'credit_card_number' => 'required_if:payment_type,cc'
]);

若驗證規則執行失敗,會產生下列錯誤訊息:

The credit card number field is required when payment type is cc.

菜鳥問與答

為什麼要進行資料驗證?

  1. 數據完整性保護: 驗證可以確保數據庫中的數據是完整的且符合預期格式。這可以防止無效或損壞的數據進入應用程序。
  2. 安全性: 驗證可以幫助防止一些常見的安全漏洞,如 SQL 注入、跨站點腳本(XSS)和跨站點請求偽造(CSRF)。通過對數據進行適當的驗證,可以降低應用程序受到攻擊的風險。
  3. 用戶體驗: 驗證可以提供更好的用戶體驗,因為它可以捕獲和提示用戶輸入錯誤,使他們能夠更容易地糾正錯誤並提交有效的數據。
  4. 程式碼可讀性和維護性: 通過在應用程序中使用驗證,代碼可以更具可讀性和維護性。它可以使程式碼更清晰,因為驗證邏輯通常是獨立的、可重用的程式碼區塊。

前後端分離情況下,前端已經處理過資料,後端還要進行資料驗證嗎?

  1. 安全性: 前端驗證通常是為了提供更好的用戶體驗,但它不能保證數據的安全性。惡意使用者可能繞過前端驗證並直接向後端提交不合法的資料,後端再次驗證可避免問題
  2. 防止錯誤: 雖然前端可以檢查一些基本的數據格式,但它無法驗證數據的完整性。後端驗證可以確保數據在進入應用程序之前是完整且符合預期格式的。
  3. 程式碼邏輯: 有些驗證可能涉及到複雜的程式碼邏輯,如:產品是否符合上層品牌關聯,前端無法驗證資料庫相關連數據,要由後端驗證

前端已經給我上層關聯的 id 跟 name,我還要驗證嗎?

這裡來個舉例:團購 Group(必勝客) 對 產品 Products(芝心披薩、章魚燒披薩…) 為一對多關係

https://ithelp.ithome.com.tw/upload/images/20231001/20162893p82YaCof3k.png

當使用者購買 芝心披薩 ,前端傳給我這筆資料,讓我新增訂單明細資料:

{
    "id": 10,
    "group_id": 46,
    "product_name": "芝心圈圈",
    "price": "199.00",
    "quantity_limit": null,
    "note": null,
    "created_at": "2023-09-27T08:50:48.000000Z",
    "updated_at": "2023-09-27T08:50:48.000000Z",
    "group": {
        "id": 46,
        "group_name": "拿坡里",   // 原本是 必勝客
        "organizer_id": 1,
        "close_price": "2000.00",
        "close_date": "2023-09-30",
        "allow_insert_product": 1,
        "status": 1,
        "created_at": "2023-09-27 08:49:51",
        "updated_at": "2023-09-27 08:49:51"
    }
}

那訂單明細要存入 拿坡里 嗎?

根據近幾個專案開發經驗,後端還是會拿 id 進行再次驗證、取得團購資料,然後以資料庫資料為主存入訂單明細,避免前端失誤或是惡意使用者篡改資料。


上一篇
後端菜鳥需要會通靈?前後端分離與不分離的資料傳遞
下一篇
Laravel 資料處理:Collection
系列文
Laravel 後端菜鳥可以知道的流程概念30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言